package mobi.greenplate.theweb.repository;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import mobi.greenplate.theweb.domain.User;
import java.util.List;
import java.util.ArrayList;
import javax.annotation.security.RolesAllowed;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import mobi.greenplate.theweb.domain.UserRole;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository("userRepository")
public class UserRepository {

    private EntityManager entityManager;

    @PersistenceContext
    void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @RolesAllowed(value = {"ROLE_USER"})
    @Transactional
    public void delete(Long id) {
        final User forDelete = entityManager.getReference(User.class, id);
        entityManager.remove(forDelete);
    }

    @Transactional
    public User save(User user) {
        user.setUserRole(UserRole.ROLE_USER);
        String hashPassword = hashPassword(user.getPassword());
        user.setPassword(hashPassword);
        return entityManager.merge(user);
    }

    private static String hashPassword(String password) {
        String hashword = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(password.getBytes());
            BigInteger hash = new BigInteger(1, md5.digest());
            hashword = hash.toString(16);
        } catch (NoSuchAlgorithmException nsae) {
            throw new RuntimeException("Something went wrong ", nsae);
        }
        return hashword;
    }

    @RolesAllowed(value = {"ROLE_USER"})
    public User findById(Long id) {
        final User user = entityManager.find(User.class, id);
        if (null == user) {
            throw new IllegalArgumentException("user with id=" + id + " not found");
        }
        return user;
    }

    public int countAll() {
        return ((Integer) entityManager.createQuery("SELECT count(o) from User o").
                getSingleResult()).intValue();
    }

    @RolesAllowed(value = {"ROLE_USER"})
    @Transactional
    public List<User> findAll(int firstResult, int maxResult) {
        final List<User> founded = entityManager.createQuery("SELECT o FROM User o").
                setFirstResult(firstResult).
                setMaxResults(maxResult).getResultList();
        return new ArrayList<User>(founded);
    }

    public boolean isUserRegistered(String userName) {
        int number = ((Integer) entityManager.createQuery("SELECT count(o) FROM User o WHERE o.userName=:userName").setParameter("userName", userName).getSingleResult()).intValue();
        return number > 0;
    }

    public boolean authenticate(String userName, String password){
        int number = ((Integer) entityManager.createQuery("SELECT count(o) FROM User o WHERE o.userName=:userName AND o.password=:password").
                setParameter("userName", userName).
                setParameter("password", hashPassword(password)).
                getSingleResult()).intValue();
        return 1==number;
    }

    public User loadRoleByUserName(String userName){
        return (User)entityManager.createQuery("SELECT o FROM User o WHERE o.userName=:userName").setParameter("userName", userName).getSingleResult();
    }
}
